// This code is licensed under New BSD Licence. For details see project page at
// http://code.google.com/p/hrissan-cocoa-helpers/source/checkout
#import <algorithm>
#import <typeinfo>

namespace math {
	template<class T>
	T clamp( T value, T mi, T ma )
	{
		if( value < mi )
			return mi;
		if( value > ma )
			return ma;
		return value;
	}
	template<class T>
	int sign( T value )
	{
		if( value < 0 )
			return -1;
		if( value > 0 )
			return 1;
		return 0;
	}
    template <class T>
    T remainder( T a, T b ) // always returs the value between 0 and b - 1. For b <= 0 result is undefined
    {
        if( a >= 0 )
            return a % b;
        T first = -((-a) % b);
        return first == 0 ? 0 : first + b;
    }
}

template<class T>
T * objective_c_cast(id val)
{
	if( ![val isKindOfClass:[T class]] )
		return 0;
	return (T *)val;
}

template<class T>
T * objective_c_cast_or_throw(id val)
{
	T * result = objective_c_cast<T>(val);
	if( !result )
		throw std::bad_cast();
	return result;
}

template<class T>
struct NSPtr
{
	explicit NSPtr():ptr(0)
	{}
	T * get()const { return ptr; }
	NSPtr(T * ptr):ptr([ptr retain])
	{}
	NSPtr(const NSPtr & other):ptr([other.ptr retain])
	{
	}
	NSPtr & operator=(const NSPtr & other)
	{
		NSPtr tmp(other);
		swap( tmp );
		return *this;
	}
	void swap(NSPtr & other)
	{
		std::swap(ptr, other.ptr);
	}
	~NSPtr()
	{
		[ptr release];
	}
	bool operator==(const NSPtr & other)const
	{
		return ptr == other.ptr;
	}
	bool operator!=(const NSPtr & other)const
	{
		return !operator==(other);
	}
private:
	T * ptr;
};


struct NSPtrNSStringLess { // simple comparison function
	bool operator()(const NSPtr<NSString> & a, const NSPtr<NSString> & b)
	{
		return [a.get() compare:b.get()] < 0;
	}
};
struct NSPtrNSStringEq { // simple comparison function
	bool operator()(const NSPtr<NSString> & a, const NSPtr<NSString> & b)
	{
		return [a.get() compare:b.get()] == 0;
	}
};
// Function definition

NSString * calculate_md5( NSString *str );

bool parseNSString( NSObject * obj, NSPtr<NSString> & result );
bool parseLongLong( NSObject * obj, long long & result );
bool parseInt( NSObject * obj, int & result );

void start_network_indicator();
void stop_network_indicator();

NSString * get_bundle_version();
NSString * get_system_version();
bool is_system_below(NSString *reqSysVer);

NSString * mac_iphone_get_place_for_files(NSString * app_name);
void mac_iphone_SecRandomCopyBytes(int len, uint8_t * bytes);
